package bsh;

import org.objectweb.asm.MethodVisitor;

import bsh.exception.CompilationFailedException;
import bsh.meta.JavaClassWrapper;
import bsh.meta.Scope;
import bsh.meta.ScopeType;
import bsh.meta.TypeWrapper;

/**
 * Compila um bloco { ... }
 * 
 * @author takeshi
 */
public class BlockNodeCompiler implements NodeCompiler {

    private final BSHBlock node;

    private final CompilationUnit unit;

    /**
     * @param node node
     * @param unit unit
     */
    public BlockNodeCompiler(BSHBlock node, CompilationUnit unit) {
        super();
        this.node = node;
        this.unit = unit;
    }

    /**
     * {@inheritDoc}
     * 
     * @see bsh.NodeCompiler#compile(org.objectweb.asm.MethodVisitor, bsh.CompilationState)
     */
    public void compile(MethodVisitor host, CompilationState state) throws CompilationFailedException {
        state.assertEmptyStack();
        Scope newScope = state.newScope(ScopeType.BLOCK);
        newScope.installStartLabel(host, state.getUnit().options());
        int start = 0;
        if (this.node.isSynchronized) {
            System.err.println("synchronized not yet implemented!");
            start++;
        }
        for (int i = start; i < this.node.jjtGetNumChildren(); i++) {
            this.unit.getNodeCompiler(this.node.getChild(i)).compile(host, state);
            checkStackEmpty(host, state);
            // we should empty the stack
        }
        checkStackEmpty(host, state);
        state.assertEmptyStack();
        newScope.installEndLabel(host, this.unit.options());
        state.popScope();
    }

    /**
     * @param host {@link MethodVisitor}
     * @param state {@link CompilationState}
     */
    public static void checkStackEmpty(MethodVisitor host, CompilationState state) {
        if (state.getStackSize() > 0) {
            state.assertStackSize(1);
            state.popStack(host);
        }
    }

    /**
     * {@inheritDoc}
     */
    public TypeWrapper nodeResultType(Scope scope) throws CompilationFailedException {
        return JavaClassWrapper.VOID_WRAPPER;
    }

}
